1.类型系统
请先思考一个问题:你见过没有类型的编程语言吗?答案当然是没有,类型是一门编程语言的基础。这是由于在计算机中,任何数值都是以一组比特简单组成的,但不同类型需要不同的硬件单元参与计算,没有类型,硬件无法区分存储器地址、脚本、字符、整数、以及浮点数。所以任何一门编程语言都有类型系统,只是有强弱之分、静态动态之分。Javascript 就是一门弱类型的、动态检查的语言。
2.为什么需要引入静态类型系统
- 提高代码的可读性
- 方便对代码分析
- 保证重构的可靠性
- 通常 IDE 能更好地支持
- 编码阶段可以捕获类型相关错误
可以看出,引入静态类型系统主要是方便代码的维护。
3.Flow vs TypeScript
众所周知,flow 是 React 源码中所使用的静态类型检查器,但是可能并没有自己用过,由于大家对 Typescript 更加熟悉,我通过与它对比,来为大家浅析下 flow 的特点。
3.1 区别
TyepScript:使用方便,工具支持健全。
- 微软出品,C# 之父 Anders Hejlsberg 参与设计
- 基于 ES6 语法(也包含是 ES7 / ES8 )
- 类型是可选的
- 可以编译出纯净、 简洁的 JavaScript 代码
Flow:健全,没有把运行时异常作为目标。
- Facebook 出品
- 是一种静态类型检查器,旨在快速查找 JavaScript 应用程序中的错误
- 不是编译器,而是检查器
- 可以很容易地通过 babel 在运行时删除类型注释
3.2 实例
3.2.1 基本
TyepScript:
1 | let obj: string; |
1 | // types can be inferred (return type) |
1 | class Sayer { |
Flow:
1 | let obj: string; |
1 | function sayIt(what: string) { |
1 | class Sayer { |
没错,基本功能上来看,两者完全一样
3.2.2 非空类型(Non-Nullable Types)
TyepScript:
1 | function foo(num: number) { |
1 | // cool |
1 | // still cool? |
1 | // error at runtime |
TypeScript 不 catch 这个
Flow:
1 | function foo(num: number) { |
Flow 可以 catch 这个,为什么呢?
因为 FLow 不会将字符串推断为返回类型
1 | // error: return undefined. This type is incompatible with string |
1 | // nullable type: the one inferred |
1 | // to fix this, we need to check the result |
但是 TypeScript 2.x 也可以 catch 这个了,通过开启strictNullChecks
总结一下:
- 在 TypeScript 1 中类型默认是可空的
- 在 TypeScript 1.x 中不为空的限制是可能的了
- 在 Flow 中类型默认是不可空的。
- 在 TysScript 2.x 中在“TSCONFIG.JSON”中使用
strictNullChecks默认类型不可空。
3.2.3 注意
1 | class Person { |
1 | // issues error as expected |
Flow 和 TypeScript 2.0 都不能 catch 这个,但是 TypeScript 中这个不会被修复了。
3.3 泛型
1 | class Animal { |
1 | class Dog extends Animal { |
1 | class Cat extends Animal { |
泛型:类型可以由其他参数化
1 | let cats: Array<Cat> = []; // can only contain cats |
到目前为止,Flow 和 TypeScript 的工作方式是一样的。但是…
TypeScript:
1 | let cats: Array<Cat> = []; // can only contain cats |
TypeScript 允许鸟和狗成为猫 :)
Flow:
1 | let cats: Array<Cat> = []; // can only contain cats |
但 Flow 不会
这是为什么呢?
TypeScript
如果要分配的类型具有更特殊的类型参数,则参数类型是兼容的
似乎最直观
允许明显错误的代码
Flow
使用泛型类型,可以从不变量(精确匹配)、协变(更特殊)和逆变(更常见)中进行选择。
Flow 中的数组具有不变的参数类型
更有表现力
更难理解
4.时间线
- 2012-10 ts 诞生
- 2013-09 ts 0.9 正式版发布
- 2014-09 ts 1.0
- 2014-11 flow 诞生
- 2016-07 React v15.2.0 引入 flow
- 2016-08 ts 2.0,引入
--strictNullChecks,支持严格空检查 - 2016-11 ts 2.1,支持对象扩展运算符
- 2017-04 ts 2.3,支持迭代器
- 2019-06 ts 3.5,支持
Omit辅助 type - 2019-10 ts 3.7,支持 Optional Chaining && Nullish Coalescing (可选链式调用”?.”与空值合并运算符”??”)
5.结语
flow 的出现一定程度推动了 js 静态类型检查的流行,让 Javascript 开发者拥抱静态类型系统,也让我们尝到了静态类型的甜头,但最终发现 Typescript 才是真香,其实可以说 flow 是促进了 typescript 的发展。